<template>
  <div class="menu-wrapper" :style="menuStyle">
    <slot name="previous" />
    <div v-if="bgImg" class="menu-shade" :style="{ backdropFilter: `blur(${gaussianBlur})` }"></div>
    <div class="menu-inner">
      <menu-item
        v-for="item of navication"
        :ref="receiveMenuItem"
        :item="item"
        :parent="{ icon: 'null', title: 'null', name: 'null', children: [] }"
        :unique-opened="uniqueOpened"
        :expand="expand"
        :init-name="initName"
        :active-name="activeName"
        :active-name-item-pos="activeNameItemPos"
        :old-active-name="oldActiveName"
        :bg="bg"
        :second-bg="secondBg"
        :styles="childStyles"
        :txt-color="txtColor"
        @closeMenuList="onCloseMenuList"
        @clickMenuItem="onClickMenuItem"
        @clickMenuItemPos="onClickMenuItemPos"
        @changeActiveName="onChangeActiveName"
        @changeMenuItemPos="onChangeMenuItemPos"
        @setExpand="onSetExpand"
      ></menu-item>
    </div>
    <slot name="append" />
  </div>
</template>

<script lang='ts'>
import { reactive, ref, computed, watch, onMounted, defineComponent } from 'vue';
import { useRoute } from 'vue-router';
import MenuItem from '@/components/navigation/MenuItem.vue';
import Navication from "@/json/navigation.json";
import { sideWidth, sideMinWidth } from '@/config/layout';
import { IMetaOptions } from '@/interface';
import { deepCopy } from '@/utils';

export default defineComponent({
  components: {
    MenuItem
  },
  props: {
    uniqueOpened: Boolean,
      bgImg: String,
      transparentBg: Boolean,
      expand: {
        type: Boolean,
        default: true
      },
      bg: {
        type: String,
        default: '#032c41'
      },
      secondBg: {
        type: String,
        default: '#02273a'
      },
      styles: {
        type: Object,
        default: () => ({})
      },
      childStyles: {
        type: Object,
        default: () => ({})
      },
      gaussianBlur: {
        type: String,
        default: '20px'
      },
      txtColor: {
        type: String,
        default: '#eee'
      }
  },
  setup(props, ctx) {
    const navication = reactive(Navication);
    const menuItem = ref<Array<any>>([]);
    const initName = ref('');
    const activeName = ref('');
    const oldActiveName = ref('');
    const activeNameItemPos = ref('');
    const banChange = ref(false);
    const route = useRoute();
    const width = computed(() => props.expand ? sideWidth : sideMinWidth);
    const menuStyle = computed(() => {
      const styles: any = {};
      styles.backgroundColor = props.bg;
      if (Object.keys(props.styles).length > 0) {
        for (let key in props.styles) {
          if (props.styles.hasOwnProperty(key)) {
            styles[key] = props.styles[key];
          }
        }
      }
      if (props.bgImg) {
        styles.backgroundImage = `url(${props.bgImg})`;
      }
      return styles;
    });
    const shadeBg = computed(() => props.transparentBg ? 'rgba(255, 255, 255, .3)' : 'rgba(0, 0, 0, .3)');
    watch(() => props.transparentBg, (v) => {
      console.log('变化', v);
    })
    /* 关闭全部子菜单 */
    watch(() => props.expand, (v) => !v && onCloseMenuList(''));

    /* 监听路由发生变化 */
    // @ts-ignore
    watch(() => route.meta.breadcrumb, (v: Array<IMetaOptions>) => {
      const breadcrumb: Array<IMetaOptions> = deepCopy(v);

      if (breadcrumb.length > 0) {
        // 拿到子级
        const last = breadcrumb.pop();

        // 展开父级
        if (breadcrumb.length > 0 && props.expand && !banChange.value) {
          breadcrumb.forEach(item => onSetExpand(item.name, true));
        }

        if (!banChange.value) {
          activeName.value = last!.name;
        }

        banChange.value = false;

      }
    });

    /* 递归子菜单 */
    const recursion = (item: any, cb: Function) => {
      cb(item);
      // item.closeMenuList(name);
      const children = item.children;
      if (children.length > 0) {
        children.forEach((child: any) => recursion(child, cb));
      }
    }

    /* 任何一个menu点击, 执行递归关闭子菜单 */
    const onCloseMenuList = (name: string) => menuItem.value.forEach(menu => recursion(menu, (item: any) => item.closeMenuList(name)));
    /* 接收menu-item组件 */
    const receiveMenuItem = (component: any) => menuItem.value.push(component);
    /* 设置当前active的导航栏名称 */
    const onClickMenuItem = (name: string) => {
      banChange.value = true;
      activeName.value = name;
    };
    /* 设置当前active导航栏名称 */
    const onChangeActiveName = (name: string) => {
      if (name !== 'null') {
        oldActiveName.value = activeName.value;
        activeName.value = name;
      }
    }
    /* 设置当前active的导航栏名称(定位导航) */
    const onClickMenuItemPos = (name: string) => {
      banChange.value = true;
      activeNameItemPos.value = name;
    };
    /* 设置当前active的导航栏名称(定位导航) */
    const onChangeMenuItemPos = (name: string) => activeNameItemPos.value = name;
    /* 设置菜单展开 */
    const onSetExpand = (name: string, state: boolean) => menuItem.value.forEach(menu => recursion(menu, (item: any) => (item.item.name === name) && item.setExpand(state)));
    onMounted(() => setTimeout(() => {
      activeName.value = (route.name as string) || 'test';
      initName.value = (route.name as string) || 'test';
    }));
    return {
      navication,
      menuItem,
      initName, activeName, oldActiveName, activeNameItemPos, banChange, route, width, menuStyle,
      shadeBg, recursion, onCloseMenuList, receiveMenuItem, onClickMenuItem, onChangeActiveName,
      onClickMenuItemPos, onChangeMenuItemPos, onSetExpand
    }
  }
})


</script>

<style scoped>
.menu-wrapper {
  width: v-bind(width);
  height: 100%;
  overflow: hidden;
  user-select: none;
  font-size: 14px;
  transition: width 0.25s ease-out;
  padding: 8px;
  background-repeat: no-repeat;
  position: relative;
  background-size: cover;
}
.menu-inner {
  width: 100%;
  height: 100%;
  overflow-y: auto;
  padding-bottom: 200px;
}
.menu-shade {
  width: 100%;
  height: 100%;
  background-color: v-bind(shadeBg);
  position: absolute;
  left: 0;
  top: 0;
}

.menu-wrapper::-webkit-scrollbar {
  width: 10px;
  border-radius: 40px;
  background-color: rgba(255, 255, 255, 0.1);
}
.menu-wrapper::-webkit-scrollbar-thumb {
  width: 5px;
  border-radius: 40px;
  background-color: rgba(255, 255, 255, 0.3);
}
.menu-wrapper::-webkit-scrollbar-button {
  display: none;
}
</style>